﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace CorporationWars
{
    public class CPU2DFire : DrawableGameComponent
    {
        Texture2D fireTexture;
        Color[] fireColor;
        int[,] fmap;
        Color[] palette = new Color[256];

        Texture2D paletteTexture;

        Random rand;

        public Point Resolution = new Point(400, 240);
        private float oxygen = .25f;
        private int minFuel = 0;
        private int maxFuel = 255;

        Texture2D fmp;

        public float Oxygen
        {
            get { return 1 - oxygen; }
            set
            {
                if (1 - value >= 0)
                    oxygen = 1 - value;
            }
        }
        public int MinFuel
        {
            get { return minFuel + 1; }
            set
            {
                if (value - 1 < maxFuel && value - 1 >= 0)
                    minFuel = value - 1;
            }
        }
        public int MaxFuel
        {
            get { return maxFuel; }
            set
            {
                if (value >= minFuel && value <= 255)
                    maxFuel = value;
            }
        }

        public CPU2DFire(Game game)
            : base(game)
        {
            BuildPalette();
            rand = new Random(DateTime.Now.Millisecond);
        }
        public CPU2DFire(Game game, Point resolution)
            : base(game)
        {
            BuildPalette();

            rand = new Random(DateTime.Now.Millisecond);

            Resolution = resolution;
        }
        protected void BuildPalette()
        {
            for (int x = 0; x < palette.Length; x++)
                palette[x] = new Color(255, Math.Min(255, x * 2), x / 3, x * 5);
            //palette[x] = new Color(x / 3, Math.Min(255, x * 2), 255, x * 5);
            //palette[x] = new Color(x / 3, 255, Math.Min(255, x * 2), x * 5);
            //palette[x] = new Color(Math.Min(255, x * 2), 255, x / 3, x * 5);
        }
        protected override void LoadContent()
        {
            base.LoadContent();

            fireTexture = new Texture2D(GraphicsDevice, Resolution.X, Resolution.Y);
            fireColor = new Color[fireTexture.Width * fireTexture.Height];

            fmp = new Texture2D(GraphicsDevice, Resolution.X, Resolution.Y);

            fmap = new int[fireTexture.Width, fireTexture.Height];

            paletteTexture = new Texture2D(GraphicsDevice, (int)Math.Sqrt(256), (int)Math.Sqrt(256));
            paletteTexture.SetData<Color>(palette);
        }

        public override void Update(GameTime gameTime)
        {
            if (!Visible)
                return;

            base.Update(gameTime);


        }
        public override void Draw(GameTime gameTime)
        {
            return;
        }

        public void Draw(Game1 game, GameTime gameTime)
        {
            int w = fmap.GetLength(0);
            int h = fmap.GetLength(1);

            int[] fm = new int[w * h];

            for (int x = 0; x < w; x++)
                fmap[x, (h - 1)] = rand.Next(minFuel, maxFuel);

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    //fmap[x, y] = ((fmap[(x - 1 + w) % w, (y + 1) % h]
                    //+ fmap[(x) % w, (y + 1) % h]
                    //+ fmap[(x + 1) % w, (y + 1) % h]
                    //+ fmap[(x) % w, (y + 2) % h])
                    //* 32) / 129;

                    //fmap[x,y] = ((fmap[(x - 1 + w) % w,(y + 1) % h]
                    //+ fmap[(x) % w,(y + 2) % h]
                    //+ fmap[(x + 1) % w, (y + 1) % h]
                    //+ fmap[(x) % w,(y + 3) % h])
                    //* 64) / 257;

                    fmap[x, y] = (int)(((fmap[(x - 1 + w) % w, (y + 1) % h]
                    + fmap[(x) % w, (y + 2) % h]
                    + fmap[(x + 1) % w, (y + 1) % h]
                    + fmap[(x) % w, (y + 2) % h])
                    * 1) / (4 + oxygen));

                    //// Water Ripple
                    //fmap[x, y] = (int)(((fmap[(x - 1 + w) % w, (y + 1) % h]
                    //+ fmap[(x) % w, (y + 1) % h]
                    //+ fmap[(x + 1) % w, (y + 1) % h]
                    //+ 0)
                    //* 1) / (3 + oxygen));
                    fm[x + (y * w)] = fmap[x, y];
                }
            }

            fmp.SetData<int>(fm);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    fireColor[x + (y * w)] = palette[fmap[x, y]];

            fireTexture.SetData<Color>(fireColor);
            if (fireTexture != null)
            {
                SpriteBatch spriteBatch = (SpriteBatch)game.Services.GetService(typeof(SpriteBatch));

                spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);
                spriteBatch.Draw(fireTexture, new Rectangle(0, 0, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight), Color.White);
                spriteBatch.End();

                // Debug
                //spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
                //spriteBatch.Draw(paletteTexture, new Rectangle(GraphicsDevice.PresentationParameters.BackBufferWidth - 128, 0, 128, 128), Color.White);
                //spriteBatch.Draw(fmp, new Rectangle(GraphicsDevice.PresentationParameters.BackBufferWidth - 256, 0, 128, 128), Color.White);
                //spriteBatch.End();
            }
        }
    }
}
